package heima_bixiangdong.test.review4;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @DESCRIPTION:    输出结果是没有问题的，但是效率还有待提升，JDK1.5之后可以改进效率问题。
 * @USER: shg
 * @DATE: 2022/11/26 17:22
 */
public class ManyProducerAndConsumerDemo {
    public static void main(String[] args) {
        // 资源对象
        Resource_1 resource_1 = new Resource_1();

        // 生产任务
        Producer_1 producer_1 = new Producer_1(resource_1);
        // 消费任务
        Consumer_1 consumer_1 = new Consumer_1(resource_1);

        // 第一个生产线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                producer_1.produceBread();
            }
        },"pro1").start();

        // 第二个生产线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                producer_1.produceBread();
            }
        },"pro2").start();

        // 第一个消费线程
        new Thread(() -> consumer_1.eatBread(),"con1").start();

        // 第二个消费线程
        new Thread(consumer_1::eatBread,"con2").start();
    }
}

// 资源对象
class Resource_1{
    private String name;
    private int count=1;

    // 标记位
    private boolean flag = false;

    public synchronized void setName(String name){
        while (flag){   // 如果标记为真，则说明盘子里面已经有面包了，生产者等待 【把if判断改成while判断】
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        this.name = name+count;
        count++;
        System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
        // 生产者生产完面包之后，就把标记改为真，并唤醒消费者进行消费
        flag = true;
        // this.notify();
        this.notifyAll();   // 多生产多消费中，需要把 this.notify()修改成this.notifyAll()
    }

    public synchronized void out(){
        while (!flag){  // 如果标记为假，则说明盘子里面没有面包，消费者等待【把if判断改成while判断】
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        // 如果标记为真，则说明盘子里有面包，消费者进行消费
        System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name);
        // 消费完后，把标记改为假，并唤醒生产者进行生产
        flag = false;
        // this.notify();  // 多生产多消费中，需要把 this.notify()修改成this.notifyAll()
        this.notifyAll();
    }
}

// 生产任务对象
@Data
@AllArgsConstructor
@NoArgsConstructor
class Producer_1{

    private Resource_1 resource;
    public void produceBread() {
        while (true){
            resource.setName("面包");
        }
    }
}

// 消费任务对象
@Data
@AllArgsConstructor
@NoArgsConstructor
class Consumer_1{
    private Resource_1 resource;

    public void eatBread() {
        while (true){
            resource.out();
        }
    }
}
